﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Quicklight.Web.Injection {

   public delegate object DefaultConstructor();

   public class ObjectManager {
      private static ObjectManager instance = new ObjectManager();
      private Dictionary<string, Dictionary<string, object>> objectStore;
      private Dictionary<string, Dictionary<string, Type>> typeStore;

      public ObjectManager() {
         objectStore = new Dictionary<string, Dictionary<string, object>>();
         typeStore = new Dictionary<string, Dictionary<string, Type>>();
      }

      public static ObjectManager Instance {
         get { return ObjectManager.instance; }
         set { ObjectManager.instance = value; }
      }

      public bool IsInstanceRegistered<TInterface>(string name) {
         return IsInstanceRegistered(typeof(TInterface), name);
      }

      public bool IsInstanceRegistered<TInterface>() {
         return IsInstanceRegistered(typeof(TInterface), "");
      }

      public bool IsInstanceRegistered(Type t, string name) {
         if (!objectStore.ContainsKey(t.FullName))
            return false;

         Dictionary<string, object> map = objectStore[t.FullName];
         return map.ContainsKey(name);
      }

      public bool IsInstanceRegistered(Type t) {
         return IsInstanceRegistered(t, "");
      }

      public void RegisterInstance<TInterface>(string name, TInterface instance) {
         RegisterInstance(typeof(TInterface), name, instance);
      }

      public void RegisterInstance<TInterface>(TInterface instance) {
         RegisterInstance(typeof(TInterface), "", instance);
      }

      public void RegisterInstance(Type t, string name, object instance) {
         if (!objectStore.ContainsKey(t.FullName))
            objectStore.Add(t.FullName, new Dictionary<string, object>());

         Dictionary<string, object> map = objectStore[t.FullName];
         map.Add(name, instance);
      }

      public void RegisterInstance(Type t, object instance) {
         RegisterInstance(t, "", instance);
      }

      public void RegisterType(Type t) {
         RegisterType(t, t, "");
      }

      public void RegisterType(Type t, string name) {
         RegisterType(t, t, name);
      }

      public void RegisterType(Type from, Type to) {
         RegisterType(from, to, "");
      }

      public void RegisterType(Type from, Type to, string name) {
         if (!typeStore.ContainsKey(from.FullName))
            typeStore.Add(from.FullName, new Dictionary<string, Type>());

         Dictionary<string, Type> map = typeStore[from.FullName];
         map.Add(name, to);
      }

      public void RegisterType<T>() {
         RegisterType(typeof(T), typeof(T), "");
      }

      public void RegisterType<T>(string name) {
         RegisterType(typeof(T), typeof(T), name);
      }

      public void RegisterType<TFrom, TTo>() where TTo : TFrom {
         RegisterType(typeof(TFrom), typeof(TTo), "");
      }

      public void RegisterType<TFrom, TTo>(string name) where TTo : TFrom {
         RegisterType(typeof(TFrom), typeof(TTo), name);
      }

      public object Resolve(Type t) {
         return Resolve(t, "");
      }

      public object Resolve(Type t, string name) {
         if (objectStore.ContainsKey(t.FullName) && objectStore[t.FullName].ContainsKey(name))
            return objectStore[t.FullName][name];
         else if (typeStore.ContainsKey(t.FullName) && typeStore[t.FullName].ContainsKey(name))
            return Activator.CreateInstance(typeStore[t.FullName][name]);
         else
            return Activator.CreateInstance(t);
      }

      public T Resolve<T>() {
         return (T)Resolve(typeof(T), "");
      }

      public T Resolve<T>(string name) {
         return (T)Resolve(typeof(T), name);
      }

   }

}
